import java.rmi.RemoteException;
import java.util.HashSet;

public class ServerObject {

	public int id;
	private Object obj;
	private int lock;

	private static final int NL = 0;
	private static final int RL = 1;
	private static final int WL = 2;

	private HashSet<Client_itf> readers = new HashSet<Client_itf>();
	private Client_itf writer;

	public ServerObject(int id, Object o) {
		this.id = id;
		this.obj = o;
	}

	public synchronized Object lock_read(Client_itf client) {

		switch (lock) {

		case NL:
			readers.add(client);
			lock = RL;
			break;

		case RL:
			readers.add(client);
			lock = RL;
			break;

		case WL:
			try {
				obj = writer.reduce_lock(id);
				readers.add(writer);
				writer = null;
				readers.add(client);
				lock = RL;
			} catch (RemoteException e) {
				e.printStackTrace();
			}
			break;

		}

		return obj;
	}// done

	public synchronized Object lock_write(Client_itf client) {

		switch (lock) {

		case NL:
			writer = client;
			lock = WL;
			break;

		case RL:
			// if the client who requests a lock_write is a reader,
			// he shall not be invalidated
			for (Client_itf c : readers) {
				try {
					if (!c.equals(client)) {
						c.invalidate_reader(id);
					}
				} catch (RemoteException e) {
					e.printStackTrace();
				}
			}
			readers.clear();
			writer = client;
			lock = WL;
			break;

		case WL:
			try {
				obj = writer.invalidate_writer(id);
				writer = client;
				lock = WL;
			} catch (RemoteException e) {
				e.printStackTrace();
			}
			break;

		}

		return obj;
	}// done
	
	// -------------------------->  Ajout etape 2 <--------------------------
	Object getObjNotSynchronised(){
		return obj;
	}

}
